const koaRouter = require('koa-router');
const koaRedis = require('koa-redis');
const Jwt = require('jsonwebtoken');
// 连接redis-cli客户端
const Store = new koaRedis().client;
const User = require('../../models/user/user');

// 这里有一个坑就是你要把库先引入进来，再解构，跟ES6里可以直接解构是有些不一样的，误区哈！
const Variable = require('../../utils/variable');
const {
    mobileReg,
    pwdReg,
    MD5_SUFFIX,
    secret
} = Variable;

// crypto.js
const myCrypto = require('../../utils/crypto');
const {
    MD5
} = myCrypto;

// 为此用户模块添加路由匹配前缀
const router = new koaRouter({
    prefix: '/api/user'
});

/**
 * 根据手机号查找某个用户
 */
const findOneUser = mobile => {
    return new Promise(async (resolve, reject) => {
        try {
            let userInfo = await User.findOne({
                mobile
            });

            resolve(userInfo);
        } catch (err) {
            reject(err);
        }
    });
};

/**
 * 请求接口地址：localhost:8080/api/user/reg
 * params: { username } 用户名
 * params: { password } 密码
 * params：{ repass } 确认密码
 * 
 * 后端返回给前端的数据格式如下：
 * {
 *      // 0表示success，1表示fail
 *      code: 0 / 1,
 *      // 提示信息
 *      msg: '手机号已被注册',
 *      // 响应的数据体
 *      responseData: {}
 * }
 */
router.post('/reg', async ctx => {
    // 手机号、原始密码、原始确认密码、MD5密码、MD5确认密码
    let {
        mobile,
        password,
        repass
    } = ctx.request.body;

    // 对前端提交过来的密码进行多次md5加密
    let md5Pass = MD5(MD5(MD5(password + MD5_SUFFIX)));

    try {
        // 1. 手机号参数没传
        if (mobile == undefined) {
            return ctx.body = {
                code: 1,
                msg: '缺少手机号参数！',
                responseData: {}
            };
        }
        
        // 2. 手机号为空
        if (mobile.trim() == '') {
            return ctx.body = {
                code: 2,
                msg: '手机号不能为空！',
                responseData: {}
            };
        }
        
        // 3. 手机号格式输入不正确
        if (!mobileReg.test(mobile)) {
            return ctx.body = {
                code: 3,
                msg: '请输入11位手机号！',
                responseData: {}
            };
        }

        // 4. 密码参数没传
        if (password == undefined) {
            return ctx.body = {
                code: 4,
                msg: '缺少密码参数！',
                responseData: {}
            };
        }
        
        // 5. 密码为空
        if (password.trim() == '') {
            return ctx.body = {
                code: 5,
                msg: '密码不能为空！',
                responseData: {}
            };
        }
        
        // 6. 密码输入格式不正确
        if (!pwdReg.test(password)) {
            return ctx.body = {
                code: 6,
                msg: '请输入8-16位字母和数字组合的区分大小写密码！',
                responseData: {}
            };
        }

        // 7. 确认密码参数没传
        if (repass == undefined) {
            return ctx.body = {
                code: 7,
                msg: '缺少确认密码参数！',
                responseData: {}
            };
        }

        // 8. 确认密码为空
        if (repass.trim() == '') {
            return ctx.body = {
                code: 8,
                msg: '确认密码不能为空！',
                responseData: {}
            };
        }

        // 9. 确认密码输入格式不正确
        if (!pwdReg.test(repass)) {
            return ctx.body = {
                code: 9,
                msg: '请输入8-16位字母和数字组合的区分大小写确认密码！',
                responseData: {}
            };
        }
        
        // 10. 密码和确认密码输入不一致
        if (password.trim() != repass.trim()) {
            return ctx.body = {
                code: 10,
                msg: '密码和确认密码不一致！',
                responseData: {}
            };
        }

        // 查找数据库里是否已经有该用户，没有的话保存数据库
        let userInfo = await findOneUser(mobile);

        // 查询到记录标识手机号已存在
        if (userInfo) {
            return ctx.body = {
                code: 11,
                msg: '手机号已被注册！',
                responseData: {}
            };
        // 程序走到这里表示，用户名没有被注册，那么将用户信息保存到数据库即可                        
        } else {
            let newsUserInfo = await User.create({
                mobile,
                password: md5Pass
            });

            // 给前端返回，恭喜，注册成功提示！
            return ctx.body = {
                code: 0,
                msg: '恭喜，注册成功！',
                responseData: newsUserInfo
            };
        }
    } catch (err) {
        console.log('用户数据插入失败：' + err);
    }
});

/**
 * 请求接口地址：localhost:8080/api/user/login
 * params: { username } 用户名
 * params: { password } 密码
 * 
 * 后端返回给前端的数据格式如下：
 * {
 *      // 0表示success，1表示fail
 *      code: 0 / 1,
 *      // 提示信息
 *      msg: '手机号不存在',
 *      // 响应的数据体
 *      responseData: {}
 * }
 */
router.post('/login', async (ctx, next) => {
    // 接收前端发送过来的手机号和密码
    let {
        mobile,
        password
    } = ctx.request.body;

    // 得到几次md5加密的密码
    let md5Pass = MD5(MD5(MD5(password + MD5_SUFFIX)));

    let loginUser = null,
        token = null;

    try {
        // 1. 手机号参数没传
        if (mobile == undefined) {
            return ctx.body = {
                code: 21,
                msg: '缺少手机号参数！',
                responseData: {}
            };
        }
        
        // 2. 手机号为空
        if (mobile.trim() == '') {
            return ctx.body = {
                code: 22,
                msg: '手机号不能为空！',
                responseData: {}
            };
        }
        
        // 3. 手机号格式输入不正确
        if (!mobileReg.test(mobile)) {
            return ctx.body = {
                code: 23,
                msg: '请输入正确的11位手机号！',
                responseData: {}
            };
        }

        // 4. 密码参数没传
        if (password == undefined) {
            return ctx.body = {
                code: 24,
                msg: '缺少密码参数！',
                responseData: {}
            };
        }
        
        // 5. 密码为空
        if (password.trim() == '') {
            return ctx.body = {
                code: 25,
                msg: '密码不能为空！',
                responseData: {}
            };
        }
        
        // 6. 密码格式输入不正确
        if (!pwdReg.test(password)) {
            return ctx.body = {
                code: 26,
                msg: '请输入8-16位字母和数字组合的区分大小写密码！',
                responseData: {}
            };
        }

        // 去数据里查询是否有该用户
        loginUser = await User.find({
            mobile
        });

        // 如果查询到该用户
        if (loginUser && loginUser.length > 0) {
            // 并且查询到的该用户的密码和当前用户填写的密码一致，那么提示登录成功
            if (loginUser[0].password.trim() == md5Pass.trim()) {
                let userToken = {
                    name: mobile
                };

                // 从redis里获取key为mobile的token值
                let redisStore = await Store.get('mobile');

                // 如果在redis里存在token，那么进行进一步验证
                if (redisStore) {
                    // 进行token验证
                    Jwt.verify(redisStore, secret, err => {
                        if (err) {
                            if (err.name == 'TokenExpiredError') {
                                // 生成token
                                token = Jwt.sign(userToken, secret, {
                                    // 过期时间1小时
                                    expiresIn: 60 * 60
                                });

                                // token存储redis
                                Store.set('mobile', token);
                            }
                            // token没有过期的话，那么直接将redis里存储的token值赋给它就可以了                                        
                        } else {
                            token = redisStore;
                        }
                    });
                    // 不存在则重新生成token                                         
                } else {
                    // 生成token
                    token = Jwt.sign(userToken, secret, {
                        // 过期时间1小时
                        expiresIn: 60 * 60
                    });

                    // token存储redis
                    Store.set('mobile', token);
                }

                return ctx.body = {
                    code: 0,
                    msg: '恭喜，登录成功！',
                    token,
                    responseData: loginUser[0]
                };
            } else {
                return ctx.body = {
                    code: 27,
                    msg: '您输入的用户名或密码有误！',
                    responseData: {}
                };
            }
        } else {
            return ctx.body = {
                code: 28,
                msg: '您输入的手机号不存在！',
                responseData: {}
            };
        }
    } catch (err) {
        console.log('err', err);
        return ctx.body = {
            code: 28,
            msg: '抱歉，登录失败！',
            responseData: {}
        };
    }
});

module.exports = router;
